package com.apinji.wxpay.service.serviceimpl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.apinji.alipay.dao.AlipayConsumeDao;
import com.apinji.alipay.dto.AlipayConsumeDto;
import com.apinji.alipay.dto.AlipayConsumeQueryDto;
import com.apinji.alipay.protocol.AlipayPayReturnResponse;
import com.apinji.alipay.protocol.BizContentRequest;
import com.apinji.alipay.sdk.AlipaySdkConfig;
import com.apinji.alipay.service.AlipayPayService;
import com.apinji.common.data.ConsumeTypeEnum;
import com.apinji.common.data.PayChannelEnum;
import com.apinji.common.data.PayStatusEnum;
import com.apinji.common.domain.TransactionRecord;
import com.apinji.common.domain.mapper.TransactionRecordMapper;
import com.apinji.common.domain.wrapper.Reply;
import com.apinji.common.plugin.*;
import com.apinji.common.plugin.fastjson.JSONUtils;
import com.apinji.unionpay.dao.TransactionRecordDao;
import com.apinji.unionpay.sdk.LogUtil;
import com.apinji.wxpay.dto.WxPayConsumeDto;
import com.apinji.wxpay.protocol.WxPayNotifyResponse;
import com.apinji.wxpay.protocol.WxPayResponse;
import com.apinji.wxpay.sdk.*;
import com.apinji.wxpay.service.WxPayPayService;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;

@Service
public class WxPayPayServiceImpl implements WxPayPayService {

    private static final String RETURN_SUCCESS_MSG = "<xml>\n" +
            "  <return_code>SUCCESS</return_code>\n" +
            "  <return_msg>OK</return_msg>\n" +
            "</xml>";

    @Autowired
    private TransactionRecordMapper transactionRecordMapper;

    @Autowired
    private TransactionRecordDao transactionRecordDao;

    @Override
    public Reply consume(WxPayConsumeDto wxPayConsumeDto, HttpServletResponse response, HttpServletRequest request) throws Exception {
        HashMap<String, String> data = new HashMap<String, String>();
        data.put("body", wxPayConsumeDto.getOrderName());
        data.put("out_trade_no", wxPayConsumeDto.getOutOrderId());
        data.put("device_info", wxPayConsumeDto.getDeviceInfo());
        String fee_type = "CNY";
        data.put("fee_type", fee_type);
        data.put("total_fee", wxPayConsumeDto.getTxnAmt()+"");
        data.put("spbill_create_ip", wxPayConsumeDto.getSpbillCreateIp());
        LogUtil.debug("notify_url------>" + WXPayConfigImpl.getInstance().getBackPayUrl());
        data.put("notify_url", WXPayConfigImpl.getInstance().getBackPayUrl());
        data.put("trade_type", "NATIVE");
        data.put("product_id", wxPayConsumeDto.getProductId());
        // data.put("time_expire", "20170112104120");
        String transactionRecordId = StrUtils.uuid();
        data.put("attach", transactionRecordId);


        WXPayConfigImpl config = WXPayConfigImpl.getInstance();
        //
        WXPay wxpay = new WXPay(config);
        //
        Map<String, String> r = wxpay.unifiedOrder(data);
        WxPayResponse wxPayResponse = JSONUtils.parseObject(JSONUtils.parseJsonStr(r), WxPayResponse.class);
        System.out.println(r);


        //======================
        TransactionRecord transactionRecord = new TransactionRecord();
        transactionRecord.setId(transactionRecordId);
        transactionRecord.setUserUUID(wxPayConsumeDto.getUserUUID());
        transactionRecord.setCreateTime(new Date());
        transactionRecord.setPayStatus(PayStatusEnum.ORDER_CREATE.getStatus());
        //transactionRecord.setCardType(bankCardToken.getCardType());
        //transactionRecord.setCardNo(consumeDto.getCardNo());
        transactionRecord.setOrderId(wxPayConsumeDto.getOrderId());
        transactionRecord.setOrderName(wxPayConsumeDto.getOrderName());
        transactionRecord.setOrderDesc(wxPayConsumeDto.getOrderDesc());
        transactionRecord.setFrontUrl(wxPayConsumeDto.getFrontUrl());
        transactionRecord.setConsumeType(ConsumeTypeEnum.PAYMENT_TYPE.getCode());
        transactionRecord.setConsumeTypeName(ConsumeTypeEnum.PAYMENT_TYPE.getName());

        transactionRecord.setOutOrderId(wxPayConsumeDto.getOutOrderId());//对外的订单编号 UUID
        transactionRecord.setPayChannel(PayChannelEnum.WECHAT_CHANNEL.getCode());//支付宝渠道

        //transactionRecord.setTxnType(txnType);
        //transactionRecord.setTxnSubType(txbSubType);
        //transactionRecord.setBizType(bizType);
        //transactionRecord.setChannelType(channelType);//渠道类型
        transactionRecord.setMerId(config.getAppID());//商户号
        transactionRecord.setTxnTime(DateUtils.getCurrentDateTime());//订单发送时间
        transactionRecord.setTxnAmt(wxPayConsumeDto.getTxnAmt());//订单金额，单位 分，不含小数点
//        transactionRecord.setCurrencyCode(fee_type);//交易币种
        //transactionRecord.setToken(token);
        //transactionRecord.setTokenPayData(tokenPayData);
        //transactionRecord.setSmsCode(consumeDto.getSmsCode());

        transactionRecord.setMemo(PayStatusEnum.ORDER_CREATE.getName());//1-交易流水已创建
        //
        transactionRecordMapper.addTransactionRecord(transactionRecord);
        //======================


        if(wxPayResponse.getResult_code() != null && wxPayResponse.getResult_code().equals("SUCCESS")) {
            transactionRecordDao.updatePayStatus(transactionRecordId, PayStatusEnum.CALLBACK_ONLY.getStatus(), PayStatusEnum.CALLBACK_ONLY.getName());
            return Mutual.success(wxPayResponse);
        } else {
            transactionRecordDao.updatePayStatus(transactionRecordId, PayStatusEnum.FAILD_DEAL.getStatus(), PayStatusEnum.FAILD_DEAL.getName());
            return Mutual.wxPayError(wxPayResponse.getErr_code(), wxPayResponse);
        }

    }


    @Override
    public void backNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String> params = new HashMap<>();
        InputStream in = request.getInputStream();
        SAXReader reader = new SAXReader();
        Document document = reader.read(in);
        Element root = document.getRootElement();
        List<Element> elementList = root.elements();
        for (Element e : elementList) {
            params.put(e.getName(), e.getTextTrim());
        }

        LogUtil.writeLog(JSONUtils.parseJsonStr(params));


        WxPayNotifyResponse wxPayNotifyResponse = JSONUtils.parseObject(JSONUtils.parseJsonStr(params), WxPayNotifyResponse.class);


        //签名验证,并校验返回的订单金额是否与商户侧的订单金额一致
        String transactionRecordId = wxPayNotifyResponse.getAttach();

        TransactionRecord transactionRecord = null;
        if(!StrUtils.isEmpty(transactionRecordId)) {
            transactionRecord = transactionRecordMapper.getOneById(transactionRecordId);
            if(null != transactionRecord && !StrUtils.isEmpty(transactionRecord.getId())) {
                if(transactionRecord.getPayStatus() == PayStatusEnum.SUCCESS_DEAL.getStatus()) {
                    LogUtil.writeLog("微信已经成功回调，且状态已经为成功");
                    //返回给银联服务器http 200状态码
                    response.getWriter().println(RETURN_SUCCESS_MSG);
                    return;
                } else {
                    transactionRecordDao.updatePayStatus(transactionRecord.getId(), PayStatusEnum.CALLBACK_ONLY.getStatus(), PayStatusEnum.CALLBACK_ONLY.getName());
                }
            }
        }
        //
        if(null == transactionRecord || StrUtils.isEmpty(transactionRecord.getId())) {
            LogUtil.writeErrorLog("未找到对应的交易记录["+transactionRecordId+"]");
            return;
        }

        //4、验证app_id是否为该商户本身。
        String app_id = wxPayNotifyResponse.getAppid();
        if(!transactionRecord.getMerId().equals(app_id)) {
            String errorMsg = "通知消息商户ID错误，系统商户ID：["+transactionRecord.getMerId()+"]，通知商户ID：["+app_id+"]";
            LogUtil.writeMessage(errorMsg);
            transactionRecordDao.updatePayStatus(transactionRecordId, PayStatusEnum.FAILD_DEAL.getStatus(), errorMsg);
            return;
        }

        //补充银联回调信息
        String queryId = wxPayNotifyResponse.getTransaction_id(); //微信支付订单号
        String traceTime = wxPayNotifyResponse.getTime_end();//支付完成时间
        transactionRecordMapper.updateCallBackInfo(transactionRecord.getId(), queryId, "", traceTime, "", "", wxPayNotifyResponse.getTotal_fee()+"", "");

        //返回成功
        if(!StrUtils.isEmpty(wxPayNotifyResponse.getResult_code()) && wxPayNotifyResponse.getResult_code().equals("SUCCESS")) {
            //交易金额正确
            if(wxPayNotifyResponse.getTotal_fee().equals(transactionRecord.getTxnAmt()+"")) {
                transactionRecordDao.updatePayStatus(transactionRecordId, PayStatusEnum.SUCCESS_DEAL.getStatus(), PayStatusEnum.SUCCESS_DEAL.getName());
                response.getWriter().println(RETURN_SUCCESS_MSG);
//
                transactionRecord = transactionRecordMapper.getOneById(transactionRecordId);
                //
                LogUtil.writeLog("开始回调参数给前端：" + transactionRecord.getFrontUrl());
                LogUtil.writeLog("开始回调参数给前端：" + JSONUtils.parseJsonStr(transactionRecord));
                String result = HttpUtils.post(transactionRecord.getFrontUrl(), JSONUtils.toJsonObject(transactionRecord));
                LogUtil.writeLog("前端回调返回：" + JSONUtils.parseJsonStr(transactionRecord));
                //
                if(null != result && result.equalsIgnoreCase("SUCCESS")) {
                    transactionRecordMapper.updateFrontRspStatus(transactionRecordId, "200");
                }

                return;
            } else {
                String errorMsg = "支付金额错误：订单金额：["+transactionRecord.getTxnAmt()+"]，实际支付金额：["+wxPayNotifyResponse.getTotal_fee()+"]";
                transactionRecordDao.updatePayStatus(transactionRecord.getId(), PayStatusEnum.ERROR_FEE.getStatus(), errorMsg);
                LogUtil.writeMessage(errorMsg);
                return;
            }
        }

    }
}
